package com.lizhaoblog.pro006scheduled.annotation;

import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.lizhaoblog.pro006scheduled.Redisson.APIResult;
import com.lizhaoblog.pro006scheduled.Redisson.RedissonLockUtils;

/**
 * 分布式锁/防重复提交 aop
 */
@Aspect
@Component
public class RedissonLockAop {
	   private static final Logger log = LoggerFactory.getLogger(RedissonLockAop.class);

    /**
     * 切点，拦截被 @RedissonLockAnnotation 修饰的方法
     */
    @Pointcut("@annotation(com.lizhaoblog.pro006scheduled.annotation.RedissonLock)")
    public void redissonLockPoint() {
    }
    //定时任务只允许一台执行
    @Around("redissonLockPoint()")
    @ResponseBody
    public APIResult checkLock(ProceedingJoinPoint pjp) throws Throwable {
        //当前线程名
        String threadName = Thread.currentThread().getName();     
        RedissonLock annotation = ((MethodSignature) pjp.getSignature()).
                getMethod().getAnnotation(RedissonLock.class);
        //生成分布式锁key的键名，以逗号分隔
        String keyParts = annotation.keyParts();
       
        if (StringUtils.isEmpty(keyParts)) {
            log.info("线程{} keyParts设置为空，不加锁", threadName);
            return (APIResult) pjp.proceed();
        } else {
            String key = keyParts;
            log.info("线程{} 要加锁的key={}", threadName, key);
            //获取锁   
            if (RedissonLockUtils.tryLock(key, 0, 5000, TimeUnit.MILLISECONDS)) {
                try {
                    log.info("线程{} 获取锁成功", threadName);
                    return (APIResult) pjp.proceed();
                } finally {
                    RedissonLockUtils.unlock(key);
                    log.info("线程{} 释放锁", threadName);
                }
            } else {
                log.info("线程{} 获取锁失败", threadName);
                return new APIResult(-9, "请求超时");
            }
        }

    }
    
    //防止请求重复提交
//    @Around("redissonLockPoint()")
//    @ResponseBody
//    public APIResult checkLock(ProceedingJoinPoint pjp) throws Throwable {
//        //当前线程名
//        String threadName = Thread.currentThread().getName();
//        log.info("线程{}------进入分布式锁aop------", threadName);
//        //获取参数列表
//        Object[] objs = pjp.getArgs();
//        //因为只有一个JSON参数，直接取第一个
//        JSONObject param = (JSONObject) objs[0];
//        //获取该注解的实例对象
//        RedissonLock annotation = ((MethodSignature) pjp.getSignature()).
//                getMethod().getAnnotation(RedissonLock.class);
//        //生成分布式锁key的键名，以逗号分隔
//        String keyParts = annotation.keyParts();
//        StringBuffer keyBuffer = new StringBuffer();
//        if (StringUtils.isEmpty(keyParts)) {
//            log.info("线程{} keyParts设置为空，不加锁", threadName);
//            return (APIResult) pjp.proceed();
//        } else {
//            //生成分布式锁key
//            String[] keyPartArray = keyParts.split(",");
//            for (String keyPart : keyPartArray) {
//                keyBuffer.append(param.getString(keyPart));
//            }
//            String key = keyBuffer.toString();
//            log.info("线程{} 要加锁的key={}", threadName, key);
//            //获取锁
//            if (RedissonLockUtils.tryLock(key, 3000, 5000, TimeUnit.MILLISECONDS)) {
//                try {
//                    log.info("线程{} 获取锁成功", threadName);
//                    return (APIResult) pjp.proceed();
//                } finally {
//                    RedissonLockUtils.unlock(key);
//                    log.info("线程{} 释放锁", threadName);
//                }
//            } else {
//                log.info("线程{} 获取锁失败", threadName);
//                return new APIResult(-9, "请求超时");
//            }
//        }
//
//    }

}
